﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FrameWork.Lib
{
    public enum ResultSeverityType : int
    {
        None = 0,
        Info = 1,
        Warning = 2,
        Error = 3,
        Critical = 4
    }

    public class Result
    {
        public Guid? ResultGUID { get; set; }
        public ResultSeverityType Severity { get; set; }
        public string Message { get; set; }
        public List<Result> SubResultList { get; set; }

        public Result()
        {
            this.SubResultList = new List<Result>();
        }

        public Result(string pMessage, ResultSeverityType pSeverity)
        {
            ResultGUID = Guid.NewGuid();
            Severity = pSeverity;
            Message = pMessage;
            this.SubResultList = new List<Result>();
        }


        public Result(Exception pException)
        {
            ResultGUID = Guid.NewGuid();
            Severity = ResultSeverityType.Critical;
            Message = pException.Message;
        }

        public void AddResult(Exception pException)
        {
            AddResult(pException.Message, ResultSeverityType.Critical);
        }

        public void AddResult(Result pResult)
        {
            if (pResult != null)
            {
                if (ResultGUID == null)
                {
                    ResultGUID = pResult.ResultGUID;
                    Severity = pResult.Severity;
                    Message = pResult.Message;
                }
                else
                {
                    if (SubResultList == null) SubResultList = new List<Result>();
                    SubResultList.Add(new Result(pResult.Message, pResult.Severity));
                }
            }
        }

        public void AddResult(string pMessage, ResultSeverityType pSeverity)
        {
            if (pMessage.HasValue())
            {
                if (ResultGUID == null)
                {
                    ResultGUID = Guid.NewGuid();
                    Severity = pSeverity;
                    Message = pMessage;
                }
                else
                {
                    if (SubResultList == null) SubResultList = new List<Result>();
                    SubResultList.Add(new Result(pMessage, pSeverity));
                }
            }
        }

        public bool HasErrorOrCritical()
        {
            bool tHasErrorOrCritical = (Severity == ResultSeverityType.Error || Severity == ResultSeverityType.Critical);

            if (!tHasErrorOrCritical && SubResultList != null)
            {
                foreach (var tSubResult in SubResultList)
                {
                    tHasErrorOrCritical = tSubResult.HasErrorOrCritical();
                    if (tHasErrorOrCritical) break;
                }
            }

            return tHasErrorOrCritical;
        }

        public List<Result> GetFlatList()
        {
            var tList = new List<Result>();

            if (this.Message.HasValue())
            {
                tList.Add(this);

                if (this.SubResultList.Count > 0)
                {
                    tList.AddRange(this.SubResultList);
                }
            }

            return tList;
        }

        public static Result New(string pMessage, ResultSeverityType pSeverity, params object[] pArgs)
        {
            return new Result(string.Format(pMessage, pArgs), pSeverity);
        }

        public static Result NewInfo(string pMessage, params object[] pArgs)
        {
            return new Result(string.Format(pMessage, pArgs), ResultSeverityType.Info);
        }

        public static Result NewError(string pMessage, params object[] pArgs)
        {
            return new Result(string.Format(pMessage, pArgs), ResultSeverityType.Error);
        }

        public static Result NewWarning(string pMessage, params object[] pArgs)
        {
            return new Result(string.Format(pMessage, pArgs), ResultSeverityType.Warning);
        }

        public static Result NewCritical(string pMessage, params object[] pArgs)
        {
            return new Result(string.Format(pMessage, pArgs), ResultSeverityType.Critical);
        }
    }
}
